package com.ustc.hewei.rpc.server.net;

import com.ustc.hewei.rpc.common.Utils.MessageSerialize;
import com.ustc.hewei.rpc.common.protocol.RequestType;
import com.ustc.hewei.rpc.common.protocol.RequestWarp;
import com.ustc.hewei.rpc.common.protocol.ResponseWarp;
import com.ustc.hewei.rpc.common.protocol.Status;
import com.ustc.hewei.rpc.server.ServiceObject;
import com.ustc.hewei.rpc.server.register.ServiceRegister;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;

/**
 * @author hewei
 * @version 1.0
 * @description: 服务端的请求消息处理类
 * @date 2022/7/27 19:13
 */

@Slf4j
public class RequestHandler {

    private ServiceRegister serviceRegister;

    public RequestHandler(ServiceRegister serviceRegister) {
        this.serviceRegister = serviceRegister;
    }

    public byte[] handler(byte[] data) {
        RequestWarp request = MessageSerialize.byteArrayToRequest(data);

        ResponseWarp response;
        if (request.getRequestType() == RequestType.KEEP_ALIVE) {
            response = new ResponseWarp(Status.KEEP_ALIVE);
        } else {
            //从本地的map集合中取出对应的服务
            ServiceObject serviceObject = serviceRegister.getServiceObject(request.getServiceName());
            if (serviceObject == null) {
                //本地并没有所请求的服务
                log.error("未找到所要调用的服务 {}", request.getServiceName());
                response = new ResponseWarp(Status.NOT_FOUND);
            } else {
                try {
                    response = new ResponseWarp(Status.SUCCESS);
                    Object object = serviceObject.getObject();
                    String method = request.getMethod();
                    Class<?>[] paramsType = request.getParamsType();
                    Object[] params = request.getParams();
                    //通过反射调用方法返回Object对象
                    Object res = object.getClass().getMethod(method, paramsType).invoke(object, params);
                    response.setData(res);
                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                    log.error("服务端反射调用方法失败", e);
                    //调用失败，设置响应的状态信息
                    response = new ResponseWarp(Status.ERROR);
                    response.setException(e);
                }
            }
        }
        return MessageSerialize.objectToByteArray(response);
    }
}
